Keras Multi-layer Perceptron
Tensorflow Premade Estimators
Tensorflow Image and Text Classification
In this section, we go through basic image classification using Multi-layer Perceptron (MLP). For testing the algorithm, we use sklearn digit dataset.
import numpy as np
import pandas as pd
from num2words import num2words
from sklearn.datasets import load_digits
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
fig, ax = plt.subplots(nrows=2, ncols=5, figsize=(17, 4), subplot_kw={'xticks': [], 'yticks': []})
ax = ax.ravel()
font = FontProperties()
font.set_family('fantasy')
digits = load_digits()
for ax, (image, label) in zip(ax, list(zip(digits.images, digits.target))):
_ = ax.imshow(image, cmap= 'Greys', interpolation='nearest')
_ = ax.set_title('%s' % num2words(label), fontproperties=font, fontsize = 16)
_ = ax.set_aspect(1)
X = digits.images/ 256.0
y = digits.target
Labels_dict = dict(zip(list(np.unique(y)), [num2words(x).title() for x in np.unique(y)]))
import plotly.express as px
from HD_DeepLearning import DatasetTargetDist
PD = dict(PieColors = px.colors.sequential.deep, TableColors = ['Navy','White'], hole = .4,
column_widths=[0.4, 0.6],textfont = 14, height = 500, tablecolumnwidth = [0.1, 0.1, 0.1],
pull = [0.1], legend_title = 'Digits', title_x = 0.5, title_y = 0.9, pie_legend = [.9, 0.25], cell_height = 22)
DatasetTargetDist(y, Target = None, Labels_dict = Labels_dict, PD = PD, orientation= 'columns')
from sklearn.model_selection import StratifiedShuffleSplit
Test_Size = 0.3
sss = StratifiedShuffleSplit(n_splits=1, test_size=Test_Size, random_state=42)
_ = sss.get_n_splits(X, y)
for train_index, test_index in sss.split(X, y):
# X
if isinstance(X, pd.DataFrame):
X_train, X_test = X.loc[train_index], X.loc[test_index]
else:
X_train, X_test = X[train_index], X[test_index]
# y
if isinstance(y, pd.Series):
y_train, y_test = y[train_index], y[test_index]
else:
y_train, y_test = y[train_index], y[test_index]
del sss
from HD_DeepLearning import Train_Test_Dist
PD.update(dict(column_widths=[0.3, 0.3, 0.3], tablecolumnwidth = [0.2, 0.4], height = 800, pull = [0.1]))
Train_Test_Dist(X_train, y_train, X_test, y_test, PD, Labels_dict)
#
import tensorflow as tf
y_train = tf.keras.utils.to_categorical(y_train, num_classes=len(Labels_dict))
y_test = tf.keras.utils.to_categorical(y_test, num_classes=len(Labels_dict))
The goal of this approach is to classify the images by focusing on the relationship between nearby pixels. A simple implementation of an image classifier can be performed in Keras using Multi-layer Perceptron (MLP) Image Classification as follows.
model = tf.keras.Sequential(name = 'MLP_Image_Classification')
model.add(tf.keras.layers.Flatten(input_shape=X[0].shape, name='Layer1'))
model.add(tf.keras.layers.Dropout(0.5))
model.add(tf.keras.layers.Dense(32, activation='relu', name='Layer2'))
model.add(tf.keras.layers.Dropout(0.5))
model.add(tf.keras.layers.Dense(len(Labels_dict), activation='softmax', name='Layer3'))
#
model.summary()
tf.keras.utils.plot_model(model, show_shapes=True, show_layer_names=True, expand_nested = True, rankdir = 'LR')
Model: "MLP_Image_Classification"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
Layer1 (Flatten) (None, 64) 0
dropout (Dropout) (None, 64) 0
Layer2 (Dense) (None, 32) 2080
dropout_1 (Dropout) (None, 32) 0
Layer3 (Dense) (None, 10) 330
=================================================================
Total params: 2,410
Trainable params: 2,410
Non-trainable params: 0
_________________________________________________________________
# Number of iterations
IT = int(5e2)+1
model.compile(optimizer= 'rmsprop', loss='binary_crossentropy', metrics=['accuracy', tf.keras.metrics.Recall()])
# Training model
history = model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs= IT, verbose = 0)
def Search_List(Key, List): return [s for s in List if Key in s]
Metrics_Names = {'loss':'Loss', 'accuracy':'Accuracy', 'mae':'MAE', 'mse':'MSE', 'recall': 'Recall'}
def Table_modify(df, Metrics_Names = Metrics_Names):
df = df.rename(columns = Metrics_Names)
df = df.reindex(sorted(df.columns), axis=1)
df.insert(loc = 0, column = 'Iteration', value = np.arange(0, df.shape[0]), allow_duplicates=False)
return df
Validation_Table = Search_List('val_',history.history.keys())
Train_Table = list(set( history.history.keys()) - set(Validation_Table))
Validation_Table = pd.DataFrame(np.array([history.history[x] for x in Validation_Table]).T, columns = Validation_Table)
Train_Table = pd.DataFrame(np.array([history.history[x] for x in Train_Table]).T, columns = Train_Table)
Validation_Table.columns = [x.replace('val_','') for x in Validation_Table.columns]
Train_Table = Table_modify(Train_Table)
Validation_Table = Table_modify(Validation_Table)
# Train Set Score
score = model.evaluate(X_train, y_train, batch_size=128, verbose = 0)
score = pd.DataFrame(score, index = model.metrics_names).T
score.index = ['Train Set Score']
# Validation Set Score
Temp = model.evaluate(X_test, y_test, batch_size=128, verbose = 0)
Temp = pd.DataFrame(Temp, index = model.metrics_names).T
Temp.index = ['Validation Set Score']
score = pd.concat([score, Temp])
score.rename(columns= Metrics_Names, inplace = True)
score = score.reindex(sorted(score.columns), axis=1)
display(score.style.format(precision=4))
| Accuracy | Loss | Recall | |
|---|---|---|---|
| Train Set Score | 0.9228 | 0.0924 | 0.8409 |
| Validation Set Score | 0.8963 | 0.0972 | 0.8259 |
Let's define some function by which we can analyze the performance of the modeling.
from HD_DeepLearning import Plot_history
PD = dict(row_heights = [0.4, 0.6], lw = 1.5, font_size=12, height = 700, yLim = 1,
th_line_color = 'Navy', th_fill_color='darkslategray', table_columnwidth = [0.4, 0.4, 0.4, 0.4],
tc_line_color = 'Navy', tc_fill_color = None, title_x = 0.46, title_y = 0.94, tb_cell_heigh = 20,
Number_Format = '%.4e')
Plot_history(Train_Table, PD, Title = 'Train Set', Table_Rows = 10, Colors = ['RoyalBlue', 'DarkGreen', 'Red'])
Plot_history(Validation_Table, PD, Title = 'Validation Set', Table_Rows = 10, Colors = ['RoyalBlue', 'DarkGreen', 'Red'])
The confusion matrix allows for visualization of the performance of an algorithm. Note that due to the size of data, here we don't provide a Cross-validation evaluation. In general, this type of evaluation is preferred.
from sklearn import metrics
# Train
y_pred = model.predict(X_train).argmax(axis = 1)
Reports_Train = pd.DataFrame(metrics.classification_report(y_train.argmax(axis = 1),
y_pred, target_names=list(Labels_dict.values()),
output_dict=True)).T
CM_Train = metrics.confusion_matrix(y_train.argmax(axis = 1), y_pred)
# Test
y_pred = model.predict(X_test).argmax(axis = 1)
Reports_Test = pd.DataFrame(metrics.classification_report(y_test.argmax(axis = 1),
y_pred, target_names=list(Labels_dict.values()),
output_dict=True)).T
CM_Test = metrics.confusion_matrix(y_test.argmax(axis = 1), y_pred)
Reports_Train = Reports_Train.reset_index().rename(columns ={'index': 'Train Set'})
Reports_Test = Reports_Test.reset_index().rename(columns ={'index': 'Test Set'})
display(Reports_Train.style.hide(axis='index').set_properties(**{'background-color': 'HoneyDew', 'color': 'Black'}).\
set_properties(subset=['Train Set'], **{'background-color': 'SeaGreen', 'color': 'White'}))
display(Reports_Test.style.hide(axis='index').set_properties(**{'background-color': 'Azure', 'color': 'Black'}).\
set_properties(subset=['Test Set'], **{'background-color': 'RoyalBlue', 'color': 'White'}))
from HD_DeepLearning import Confusion_Mat
PD = dict(FS = (16, 6), annot_kws = 10, shrink = .6, Labels = list(Labels_dict.values()))
Confusion_Mat(CM_Train, CM_Test, PD = PD, n_splits = None)
| Train Set | precision | recall | f1-score | support |
|---|---|---|---|---|
| Zero | 0.976190 | 0.991935 | 0.984000 | 124.000000 |
| One | 0.915254 | 0.850394 | 0.881633 | 127.000000 |
| Two | 0.951613 | 0.951613 | 0.951613 | 124.000000 |
| Three | 0.925620 | 0.875000 | 0.899598 | 128.000000 |
| Four | 0.960630 | 0.960630 | 0.960630 | 127.000000 |
| Five | 0.957627 | 0.889764 | 0.922449 | 127.000000 |
| Six | 0.984127 | 0.976378 | 0.980237 | 127.000000 |
| Seven | 0.878571 | 0.984000 | 0.928302 | 125.000000 |
| Eight | 0.827068 | 0.901639 | 0.862745 | 122.000000 |
| Nine | 0.862903 | 0.849206 | 0.856000 | 126.000000 |
| accuracy | 0.922832 | 0.922832 | 0.922832 | 0.922832 |
| macro avg | 0.923960 | 0.923056 | 0.922721 | 1257.000000 |
| weighted avg | 0.924277 | 0.922832 | 0.922770 | 1257.000000 |
| Test Set | precision | recall | f1-score | support |
|---|---|---|---|---|
| Zero | 1.000000 | 0.962963 | 0.981132 | 54.000000 |
| One | 0.857143 | 0.763636 | 0.807692 | 55.000000 |
| Two | 0.862069 | 0.943396 | 0.900901 | 53.000000 |
| Three | 0.927273 | 0.927273 | 0.927273 | 55.000000 |
| Four | 0.927273 | 0.944444 | 0.935780 | 54.000000 |
| Five | 0.980000 | 0.890909 | 0.933333 | 55.000000 |
| Six | 0.981132 | 0.962963 | 0.971963 | 54.000000 |
| Seven | 0.815385 | 0.981481 | 0.890756 | 54.000000 |
| Eight | 0.823529 | 0.807692 | 0.815534 | 52.000000 |
| Nine | 0.807692 | 0.777778 | 0.792453 | 54.000000 |
| accuracy | 0.896296 | 0.896296 | 0.896296 | 0.896296 |
| macro avg | 0.898150 | 0.896254 | 0.895682 | 540.000000 |
| weighted avg | 0.898622 | 0.896296 | 0.895934 | 540.000000 |
import seaborn as sns
Pred = model.predict(X_test)
from HD_DeepLearning import MLP_Pred_Plot
Pred_Labels = np.argmax(Pred, axis = 1)
True_Labels = np.argmax(y_test, axis =1)
# redicted Labels (Correct)
C = np.where(abs(Pred_Labels - True_Labels) == 0)[0]
# Predicted Labels (Wrong)
W = np.nonzero(abs(Pred_Labels - True_Labels))[0]
For example, we can randomly pick an entry from the correctly predicted labels list
MLP_Pred_Plot(np.random.choice(C), Pred, X_test, y_test, Labels_dict)
Similarly, from the wrongly predicted labels list
MLP_Pred_Plot(np.random.choice(W), Pred, X_test, y_test, Labels_dict)